=========
Scripting
=========

Los *scripts* o guiones permiten añadir interactividad a la página.

Se recomienda proporcionar alternativas a los guiones siempre
que sea posible, pues muchos usuarios los desabilitan o no pueden
utilizarlos.


El elemento ``script``
======================

Permite incluir un guion dinámico y bloques de datos en los documentos.
Este elemento no representa contenido para el usuario.

El atributo ``type`` permite indicar cómo debe interpretar el navegador el
contenido de la etiqueta.

- Si se omite el atributo o se establece a un tipo MIME de JavaScript,
  el guion se interpreta como código JavaScript.

- Si se establece el atributo a otro valor, el guion se interpreta como un
  bloque de datos que no es procesado. Se debe utilizar un tipo MIME válido.

.. code-block:: html

   <head>
     <script>
        alert('¡Hola, mundo!');
     </script>
   </head>

El atributo ``src`` indica la ruta donde se encuentra el guion. En este caso
no se debe incluir nada dentro de la etiqueta ``<script>``.

.. code-block:: html

   <body>
     <p>Párrafo</p>
     <script src="externo.js"></script>
   </body>

El atributo ``charset`` establece la codificación de caracteres del guion.
Este atributo no debe especificarse si no existe el atributo ``src``.

Los atributos ``async`` y ``defer`` son valores booleanos que indican
cómo se debe ejecutar el guion.

Para guiones normales, si el atributo ``async`` está presente, el guion será
obtenido en paralelo y evaluado tan pronto como esté disponible. Si no está
presente el atributo ``async`` pero está presente el atributo ``defer``, el
guion se obtiene en paralelo y se evalúa cuando la página haya terminado de
interpretarse. Si ningún atributo está presente, el guion es
obtenido y evaluado inmediatamente, bloqueando el intérprete hasta que ambas
tareas se hayan completado

Esto se resume con el siguiente diagrama:

.. image:: imagenes/asyncdefer.png

Se pueden usar varios guiones en una misma página. En el siguiente ejemplo
se utilza un guion interno y otro externo... El interno se trata del
mapa de un juego; el externo es el motor del juego.

.. code-block:: html

   <script src="motor-de-juego.js"></script>
   <script type="text/x-game-map">
   ........U.........e
    o............A....e
    .....A.....AAA....e
    .A..AAA...AAAAA...e
    </script>

El elemento ``noscript``
========================

Este elemento no representa nada si están habilitados los guiones. Se
utiliza para permitir presentar un marcado alternativo a aquellos usuarios
que no tienen habilitados los guiones.

.. code-block:: html

   <form action="calcSquare.php">
     <p>
       <label for=x>Number</label>:
       <input id="x" name="x" type="number">
     </p>
     <script>
  var x = document.getElementById('x');
  var output = document.createElement('p');
  output.textContent = 'Escribe un número y lo multiplicaré por sí mismo inmediatamente';
  x.form.appendChild(output);
  x.form.onsubmit = function () { return false; }
  x.oninput = function () {
    var v = x.valueAsNumber;
    output.textContent = ' La raíz de ' + v + ' es ' + v * v;
  };
     </script>
     <noscript>
       <input type=submit value="Calculate Square">
     </noscript>
   </form>

El elemento ``template``
========================

Sirve para declarar fragmentos de HTML que pueden ser clonados e insertados
en el documento por un guion.

Cuando se carga la página, el contenido del elemento ``<template>`` no se
muestra.

.. code-block:: html

   <body>
       <table>
           <tbody>
           </tbody>
       </table>
      <template id="fila">
          <tr>
              <td>
              <td>
              <td>
              <td>
      </template>
      <script>
      var tbody = document.getElementsByTagName('tbody')[0];
      const NUMBER_OF_COLUMNS = 4;
      const NUMBER_OF_ROWS = 10;

      var plantilla_fila = document.querySelector('#fila');

      for (let i = 0; i < NUMBER_OF_ROWS; i++) {
          var fila = plantilla_fila.content.cloneNode(true);
          for (let j = 0; j < NUMBER_OF_COLUMNS; j++) {
              let mensaje = 'Fila ' + (i + 1) + '; Columna ' + (j + 1);
              var celda = fila.querySelectorAll('td')[j];
              celda.innerHTML = mensaje;
          }
          tbody.appendChild(fila);
      }
      </script>
   </body>

El elemento ``canvas``
========================

Canvas (o lienzo traducido al español) es un elemento HTML que permite la
generación de gráficos dinámicamente por medio de guiones. Entre otras
cosas permite la renderización interpretada dinámica de gráficos 2D y
mapas de bits, así como animaciones con estos gráficos.

El elemento ``<canvas>`` se muestra en un navegador con el tamaño
establecido en sus atributos ``width`` y ``height``. Se suele utilizar el
atributo ``id`` para permitir acceder a este elemento mediante JavaScript.

.. code-block:: html

   <canvas id="ejemplo" width="200" height="200">
   Este texto se muestra si tu navegador no soporta el elemento canvas de HTML 5.
   </canvas>

Utilizando JavaScript se puede dibujar en el lienzo...

.. code-block:: html
   :emphasize-lines: 4-10

   <canvas id="ejemplo" width="600" height="400">
   Este texto se muestra si tu navegador no soporta el elemento canvas de HTML 5.
   </canvas>
   <script>
     var ejemplo = document.getElementById('ejemplo');
     var context = ejemplo.getContext('2d');
     context.fillStyle = 'aquamarine';
     context.fillRect(90, 70, 100, 70);
   </script>

El anterior ejemplo dibuja un rectángulo en la coordenada 30, 30 con 100
píxeles de ancho y 120 de alto. El eje 0, 0 comienza en la esquina superior
izquierda del canvas, como se puede ver en la siguiente imagen.

.. image:: imagenes/coordenadas-canvas.png
